package org.jeecg.modules.bpm.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.persistence.entity.TaskEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl;
import org.activiti.engine.impl.pvm.process.TransitionImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.CommonUtils;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.bpm.dto.ActHiActinstDTO;
import org.jeecg.modules.bpm.dto.TaskDTO;
import org.jeecg.modules.bpm.dto.UserAgentDTO;
import org.jeecg.modules.bpm.mapper.ActivitiMapper;
import org.jeecg.modules.bpm.service.ActivitiService;
import org.jeecg.modules.bpm.util.SqlUtil;
import org.jeecg.modules.extbpm.process.common.WorkFlowGlobals;
import org.jeecg.modules.extbpm.process.entity.ExtActFlowData;
import org.jeecg.modules.extbpm.process.entity.ExtActTaskNotification;
import org.jeecg.modules.extbpm.process.mapper.ExtActFlowDataMapper;
import org.jeecg.modules.extbpm.process.mapper.ExtActProcessMapper;
import org.jeecg.modules.extbpm.process.mapper.ExtActTaskNotificationMapper;
import org.jeecg.modules.extbpm.util.CommonRandomUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service("activitiService")
public class ActivitiServiceImpl implements ActivitiService {
	private static final String APPLY_USER_ID = CommonRandomUtil.trim("applyUserId");
	@Autowired
	private RuntimeService runtimeService;
	@Autowired
	private TaskService taskService;
	@Autowired
	private RepositoryService repositoryService;
	@Autowired
	private HistoryService historyService;
	@Autowired
	private ActivitiMapper activitiMapper;
	@Autowired
	private ISysBaseAPI sysBaseAPI;
	@Autowired
	private ExtActTaskNotificationMapper extActTaskNotificationMapper;
	@Autowired
	private ExtActFlowDataMapper extActFlowDataMapper;
	@Autowired
	private ExtActProcessMapper extActProcessMapper;

	@Override
	public List<TaskDTO> findPriTodoTasks(String userId, HttpServletRequest request) {
		try {
			return findBaseTodoTasks(true, userId, request);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	@Override
	public List<TaskDTO> findGroupTodoTasks(List<String> roles,HttpServletRequest request) {
		try {
			StringBuilder roleIds = new StringBuilder();
			//用户所在的组可能有多个，需要合并
			for(String role:roles){
				roleIds.append(role).append(",");
			}
			roleIds.deleteCharAt(roleIds.length()-1);
			List<TaskDTO> resulttemp = findBaseTodoTasks(false,roleIds.toString(),request);
			return resulttemp;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 查询待办任务-基础代码
	 * 
	 * @param isPri        是否只查询用户私有的
	 * @param id           标识：username或者rolecode
	 * @return
	 * @throws  
	 * @throws Exception 
	 */
	private List<TaskDTO> findBaseTodoTasks(boolean isPri, String id, HttpServletRequest request) throws Exception {
		List<TaskDTO> results = new ArrayList<TaskDTO>();
		// 分页参数
		Integer page = oConvertUtils.getInt(request.getParameter("pageNo"),1);
		Integer rows = oConvertUtils.getInt(request.getParameter("pageSize"),10);
		Integer start = (page - 1) * rows;
		Integer end = page * rows - 1;
		// 建立临时集合
		List<Task> tempList = new ArrayList<Task>();
		List<Task> unsignedTasks;
		if (isPri) {
//			//查询备选人名下的任务
//			TaskService taskService = processEngine.getTaskService();
//			TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateUser(userId).orderByTaskCreateTime().desc().active();
//			List<Task> todoListGroup = taskQuery.list();// .taskCandidateGroup("hr").active().list();
//			tempList.addAll(todoListGroup);
//
//			//查询个人名下的任务
//			TaskQuery tq = taskService.createTaskQuery().taskAssignee(userId).orderByTaskCreateTime().desc().orderByTaskPriority().desc();
//			tq = installQueryParam(tq, request);
////			List<Task> todoList = tq.listPage(start, end);
//			List<Task> todoList = tq.list();
//			tempList.addAll(todoList);
			
			String userName = request.getParameter("userName");
			StringBuilder userNamesb = new StringBuilder("");
			if(oConvertUtils.isNotEmpty(userName)){
				List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().variableValueEquals(APPLY_USER_ID, userName).list();
				if(processInstanceList!=null&&processInstanceList.size()>0){
					for(int i=0;i<processInstanceList.size();i++){
						if(i==0){
							userNamesb.append("'"+processInstanceList.get(i).getProcessInstanceId()+"'");
						}else{
							userNamesb.append(",'"+processInstanceList.get(i).getProcessInstanceId()+"'");
						}
					}
				}
			}
			String inUserNameStr = userNamesb.toString();
			//TODO 
			String procDefId = request.getParameter("processDefinitionId");
			String procDefName = request.getParameter("processDefinitionName");
			
			
			StringBuilder sb = new StringBuilder("");
			sb.append("select  * ").append("from (");
			sb.append("(select distinct RES.* ");
			sb.append(" from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
			sb.append(" INNER JOIN ACT_RE_PROCDEF ARP ON ARP.ID_ = RES.PROC_DEF_ID_ ");
			sb.append("WHERE I.TYPE_ = 'candidate' ");
			sb.append("	and ( I.USER_ID_ = #{userid}  or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = #{userid}  ) ");
			sb.append(" ) ").append(" and RES.SUSPENSION_STATE_ = 1 ");
			if(oConvertUtils.isNotEmpty(procDefId)){
				sb.append("  AND RES.PROC_DEF_ID_ LIKE #{procDefId} ");
			}
			if(oConvertUtils.isNotEmpty(procDefName)){
				sb.append("  AND ARP.NAME_  LIKE #{procDefName} ");
			}
			//流程发起人查询问题
			if(oConvertUtils.isNotEmpty(userName)){
				if(oConvertUtils.isNotEmpty(inUserNameStr)){
					sb.append("  AND RES.PROC_INST_ID_ in ("+inUserNameStr+") ");
				}else{
					sb.append("  AND RES.PROC_INST_ID_ in ('-1') ");
				}
			}
			sb.append(") union ");
			sb.append("(select distinct RES.* ");
			sb.append(" from ACT_RU_TASK RES ");
			sb.append(" INNER JOIN ACT_RE_PROCDEF ARP ON ARP.ID_ = RES.PROC_DEF_ID_ ");
			sb.append("WHERE RES.ASSIGNEE_ = #{userid} ");
			if(oConvertUtils.isNotEmpty(procDefId)){
				sb.append("  AND RES.PROC_DEF_ID_ LIKE #{procDefId} ");
			}
			if(oConvertUtils.isNotEmpty(procDefName)){
				sb.append("  AND ARP.NAME_  LIKE #{procDefName} ");
			}
			//流程发起人查询问题
			if(oConvertUtils.isNotEmpty(userName)){
				if(oConvertUtils.isNotEmpty(inUserNameStr)){
					sb.append("  AND RES.PROC_INST_ID_ in ("+inUserNameStr+") ");
				}else{
					sb.append("  AND RES.PROC_INST_ID_ in ('-1') ");
				}
			}
			sb.append(" )) v ");
			sb.append(" order by v.CREATE_TIME_ desc, v.PRIORITY_ desc ");
			
			String dbType = CommonUtils.getDatabaseType();
			String sql = SqlUtil.createPageSql(dbType, sb.toString(), page, rows);
			log.info("我的任务:"+sql);
			NativeTaskQuery query = taskService.createNativeTaskQuery()
					.sql(sql)
			        .parameter("userid", id);
			log.info("id: " + id);
					if(oConvertUtils.isNotEmpty(procDefId)){
						query.parameter("procDefId", "%"+procDefId+"%");
						log.info("procDefId: " + procDefId);
					}
					if(oConvertUtils.isNotEmpty(procDefName)){
						query.parameter("procDefName", "%"+procDefName+"%");
						log.info("procDefName: " + procDefName);
					}
			        List<Task> pretasks = query.list(); 
					tempList.addAll(pretasks);
		}else {
			TaskQuery tq = taskService.createTaskQuery().taskCandidateGroupIn(Arrays.asList(id.split(","))).orderByTaskCreateTime().desc().orderByTaskPriority().desc();
			tq = installQueryParam(tq,request);
			unsignedTasks = tq.listPage(start,end);
			tempList.addAll(unsignedTasks);
		}
		
		//
		for(Task t:tempList) {
			TaskDTO dto = new TaskDTO();
			
			//任务处理人ID
			String taskAssigneeId =  t.getAssignee()==null?"":t.getAssignee();
			if(oConvertUtils.isNotEmpty(taskAssigneeId)) {
				LoginUser sysUser = sysBaseAPI.getUserByName(taskAssigneeId);
				dto.setTaskAssigneeName(sysUser!=null?sysUser.getRealname():"");
			}
			
			//流程所有人
//			String tenantId = t.getTenantId();
			String  applyUserId = historyService.createHistoricProcessInstanceQuery().processInstanceId(t.getProcessInstanceId()).singleResult().getStartUserId();//获取发起人
			if(oConvertUtils.isNotEmpty(applyUserId)) {
				LoginUser ownerSysUser = sysBaseAPI.getUserByName(applyUserId);
				dto.setProcessApplyUserName(ownerSysUser!=null?ownerSysUser.getRealname():"");
			}
			
			//流程实例ID
			String processInstanceId = t.getProcessInstanceId();
			ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
			
			//流程定义
//			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(t.getProcessDefinitionId()).singleResult();
			
			dto.setId(t.getId());
//			dto.setTaskAssigneeName(sysUser!=null?sysUser.getRealname():"");
			dto.setTaskAssigneeId(taskAssigneeId);
			dto.setTaskBeginTime(t.getCreateTime());
			dto.setTaskName(t.getName());
			dto.setTaskId(t.getTaskDefinitionKey());
			dto.setTaskEndTime(t.getDueDate());
			dto.setProcessInstanceId(t.getProcessInstanceId());
			dto.setProcessApplyUserId(applyUserId);
//			dto.setProcessApplyUserName(ownerSysUser!=null?ownerSysUser.getRealname():"");
			dto.setProcessDefinitionId(processInstance.getProcessDefinitionId());
			dto.setProcessDefinitionName(processInstance.getProcessDefinitionName());
			String bpmBizTitle = (String)taskService.getVariable(t.getId(), WorkFlowGlobals.BPM_BIZ_TITLE);
			if(bpmBizTitle!=null){
				dto.setBpmBizTitle(bpmBizTitle);
			}
			//催办消息
			dto.setTaskUrge(false);
			if(oConvertUtils.isNotEmpty(dto.getTaskAssigneeId())
					&&oConvertUtils.isNotEmpty(dto.getProcessInstanceId())
					&&oConvertUtils.isNotEmpty(dto.getId())) {
				LambdaQueryWrapper<ExtActTaskNotification> queryWrapper = new LambdaQueryWrapper<ExtActTaskNotification>();
				queryWrapper.eq(ExtActTaskNotification::getProcInstId, dto.getProcessInstanceId());
				queryWrapper.eq(ExtActTaskNotification::getTaskId, dto.getId());
				queryWrapper.eq(ExtActTaskNotification::getTaskAssignee, dto.getTaskAssigneeId());
				int notifyCount = extActTaskNotificationMapper.selectCount(queryWrapper);
				if(notifyCount>0) {
					dto.setTaskUrge(true);
				}
			}
			
			results.add(dto);
		}
		return results;
	}
	
	
	

	@Override
	public Long countPriTodaoTask(String userid, HttpServletRequest request) {
		Long size = 0L;
		// 根据当前人的ID查询
		String userName2 = request.getParameter("userName");
		StringBuilder userNamesb = new StringBuilder("");
		if (oConvertUtils.isNotEmpty(userName2)) {
			List<ProcessInstance> processInstanceList = runtimeService.createProcessInstanceQuery().variableValueEquals(APPLY_USER_ID, userName2).list();
			if (processInstanceList != null && processInstanceList.size() > 0) {
				for (int i = 0; i < processInstanceList.size(); i++) {
					if (i == 0) {
						userNamesb.append("'" + processInstanceList.get(i).getProcessInstanceId() + "'");
					} else {
						userNamesb.append(",'" + processInstanceList.get(i).getProcessInstanceId() + "'");
					}
				}
			}
		}
		String inUserNameStr = userNamesb.toString();
		// 查询条件
		String procDefId = request.getParameter("processDefinitionId");
		StringBuilder sb = new StringBuilder("");
		sb.append("select  count(*) ").append("from (");
		sb.append("(select distinct RES.* ").append("from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ ");
		sb.append("WHERE RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate' ");
		sb.append("	and ( I.USER_ID_ = #{userid}  or I.GROUP_ID_ IN ( select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = #{userid}  ) ");
		sb.append(" ) ").append(" and RES.SUSPENSION_STATE_ = 1 ");
		if (oConvertUtils.isNotEmpty(procDefId)) {
			sb.append("  AND RES.PROC_DEF_ID_ LIKE #{procDefId} ");
		}
		//流程发起人查询问题
		if (oConvertUtils.isNotEmpty(userName2)) {
			if (oConvertUtils.isNotEmpty(inUserNameStr)) {
				sb.append("  AND RES.PROC_INST_ID_ in (" + inUserNameStr + ") ");
			} else {
				sb.append("  AND RES.PROC_INST_ID_ in ('-1') ");
			}
		}
		sb.append(") union ");
		sb.append("(select distinct RES.* ").append("from ACT_RU_TASK RES ");
		sb.append("WHERE RES.ASSIGNEE_ = #{userid} ");
		if (oConvertUtils.isNotEmpty(procDefId)) {
			sb.append("  AND RES.PROC_DEF_ID_ LIKE #{procDefId} ");
		}
		if (oConvertUtils.isNotEmpty(userName2)) {
			if (oConvertUtils.isNotEmpty(inUserNameStr)) {
				sb.append("  AND RES.PROC_INST_ID_ in (" + inUserNameStr + ") ");
			} else {
				sb.append("  AND RES.PROC_INST_ID_ in ('-1') ");
			}
		}
		sb.append(" )) v ");
		log.debug("我的任务count:"+sb.toString());
		NativeTaskQuery query = taskService.createNativeTaskQuery().sql(sb.toString()).parameter("userid", userid);
		if (oConvertUtils.isNotEmpty(procDefId)) {
			query.parameter("procDefId", "%" + procDefId + "%");
		}
		size = query.count();
		return size;
	}
	
	@Override
	public Long countGroupTodoTasks(List<String> roles, HttpServletRequest request) {
		//查询条件
//		String procDefId = request.getParameter("processDefinitionId");
//		String procName = request.getParameter("processDefinitionName");
		Long size = 0L;
		// 根据当前组的ID查询
		TaskQuery  tq =taskService.createTaskQuery().taskCandidateGroupIn(roles).orderByTaskPriority().desc().orderByTaskCreateTime().desc();
		installQueryParam(tq,request);
		size = tq.count();
		return size;
	}
	
	/**
	 * 获取业务ID
	 * 
	 * @param task
	 * @return
	 */
	private String getBusinessKeyByTask(Task task) {
		String businessKey = "";
		TaskEntity taskEntity = (TaskEntity) taskService.createTaskQuery().taskId(task.getId()).singleResult();
		HistoricProcessInstance hiproins = historyService.createHistoricProcessInstanceQuery().processInstanceId(taskEntity.getProcessInstanceId()).singleResult();
		if (hiproins != null) {
			if (hiproins.getSuperProcessInstanceId() != null && hiproins.getBusinessKey() == null) {
				hiproins = historyService.createHistoricProcessInstanceQuery().processInstanceId(hiproins.getSuperProcessInstanceId()).singleResult();
				businessKey = hiproins.getBusinessKey();
			} else {
				businessKey = hiproins.getBusinessKey();
			}
		}
		return businessKey;
	}

	/**
	 * 拼装过滤条件
	 * 
	 * @param tq
	 * @param request
	 * @return
	 */
	private TaskQuery installQueryParam(TaskQuery tq, HttpServletRequest request) {
		// 查询条件
		String procDefId = request.getParameter("processDefinitionId");
		String procName = request.getParameter("processDefinitionName");
		if (oConvertUtils.isNotEmpty(procDefId)) {
			tq = tq.processDefinitionId(procDefId);
		}
		if (oConvertUtils.isNotEmpty(procName)) {
//			tq = tq.processDefinitionName(procName);
			tq = tq.processDefinitionNameLike(procName);
		}
		return tq;
	}

	@Override
	public Task getTask(String taskId) {
		return taskService.createTaskQuery().taskId(taskId).singleResult();
	}
	
	/**
	 * 查询流程的所有节点
	 * @param taskId
	 * @return
	 */
	@Override
	public List<Map> getAllTaskNode(String taskId) {
		List<Map> list = new ArrayList();
		Task task = getTask(taskId);
		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());
		List<ActivityImpl> activitiList = def.getActivities(); // rs是指RepositoryService的实例
		for (ActivityImpl activityImpl : activitiList) {
			Map m = new HashMap();
			String id = activityImpl.getId();
			m.put("taskKey", id);
			String name = (String)activityImpl.getProperty("name");
			m.put("name", name);
			list.add(m);
		}
		return list;
	}

	/**
	 * 根据流程processkey获取该流程下已经发布的流程
	 * @param processkey
	 * @return
	 */
	@Override
	public List<ProcessDefinition> processDefinitionListByProcesskey(String processkey) {
		return repositoryService.createProcessDefinitionQuery().processDefinitionKey(processkey).list();
	}

	@Override
	public Page<TaskDTO> findHistoryTasks(Page page,String userName, HttpServletRequest request) {
		String procDefId = request.getParameter("processDefinitionId");
		String procName = request.getParameter("processDefinitionName");
		List<TaskDTO> result = activitiMapper.getHistoryTasks(page,userName,procDefId, procName);
		for(TaskDTO task:result) {
			task.setBpmBizTitle(this.getHisVarinst(WorkFlowGlobals.BPM_BIZ_TITLE, task.getProcessInstanceId()));
			//任务处理人ID
			String taskAssigneeId =  task.getTaskAssigneeId();
			if(oConvertUtils.isNotEmpty(taskAssigneeId)) {
				LoginUser sysUser = sysBaseAPI.getUserByName(taskAssigneeId);
				task.setTaskAssigneeName(sysUser.getRealname());
			}
			
			//流程所有人
//			String tenantId = t.getTenantId();
			String  applyUserId = task.getProcessApplyUserId();//获取发起人
			if(oConvertUtils.isNotEmpty(applyUserId)) {
				LoginUser ownerSysUser = sysBaseAPI.getUserByName(applyUserId);
				task.setProcessApplyUserName(ownerSysUser.getRealname());
			}
		}
		return page.setRecords(result);
	}
	
	@Override
	public Page<TaskDTO> findAllHistoryTasks(Page page,HttpServletRequest request) {
		String procDefId = request.getParameter("processDefinitionId");
		String procName = request.getParameter("processDefinitionName");
		List<TaskDTO> result = activitiMapper.getAllHistoryTasks(page,procDefId, procName);
		for(TaskDTO task:result) {
			task.setBpmBizTitle(this.getHisVarinst(WorkFlowGlobals.BPM_BIZ_TITLE, task.getProcessInstanceId()));
			//任务处理人ID
			String taskAssigneeId =  task.getTaskAssigneeId();
			if(oConvertUtils.isNotEmpty(taskAssigneeId)) {
				LoginUser sysUser = sysBaseAPI.getUserByName(taskAssigneeId);
				task.setTaskAssigneeName(sysUser.getRealname());
			}
			
			//流程所有人
//			String tenantId = t.getTenantId();
			String  applyUserId = task.getProcessApplyUserId();//获取发起人
			if(oConvertUtils.isNotEmpty(applyUserId)) {
				LoginUser ownerSysUser = sysBaseAPI.getUserByName(applyUserId);
				task.setProcessApplyUserName(ownerSysUser.getRealname());
			}
		}
		return page.setRecords(result);
	}
	
	@Override
	public Page<TaskDTO> findAllCcHistoryTasks(Page page,String username,HttpServletRequest request) {
		String procDefId = request.getParameter("processDefinitionId");
		String procName = request.getParameter("processDefinitionName");
		List<TaskDTO> result = activitiMapper.getAllCcHistoryTasks(page,username,procDefId, procName);
		for(TaskDTO task:result) {
			task.setBpmBizTitle(this.getHisVarinst(WorkFlowGlobals.BPM_BIZ_TITLE, task.getProcessInstanceId()));
			//任务处理人ID
			String taskAssigneeId =  task.getTaskAssigneeId();
			if(oConvertUtils.isNotEmpty(taskAssigneeId)) {
				LoginUser sysUser = sysBaseAPI.getUserByName(taskAssigneeId);
				task.setTaskAssigneeName(sysUser.getRealname());
			}
			
			//流程所有人
//			String tenantId = t.getTenantId();
			String  applyUserId = task.getProcessApplyUserId();//获取发起人
			if(oConvertUtils.isNotEmpty(applyUserId)) {
				LoginUser ownerSysUser = sysBaseAPI.getUserByName(applyUserId);
				task.setProcessApplyUserName(ownerSysUser.getRealname());
			}
		}
		return page.setRecords(result);
	}
	
	/**
	 * 通过任务节点ID，获取当前节点 分支
	 */
	@Override
	public List getOutTransitions(String taskId) {
		List<PvmTransition> outTransitions = null;
		List<Map> trans = new ArrayList();
		Task task = getTask(taskId);
		ProcessDefinitionEntity def = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());
		List<ActivityImpl> activitiList = def.getActivities(); // rs是指RepositoryService的实例

		String excId = task.getExecutionId();
		ExecutionEntity execution = (ExecutionEntity) runtimeService
				.createExecutionQuery().executionId(excId).singleResult();
		String activitiId = execution.getActivityId();

		for (ActivityImpl activityImpl : activitiList) {
			String id = activityImpl.getId();
			if (activitiId.equals(id)) {
				outTransitions = activityImpl.getOutgoingTransitions();// 获取从某个节点出来的所有线路
				for (PvmTransition tr : outTransitions) {
					if(tr.getId()!=null){
						Map m = new HashMap();
						//获取分支线路的名字，如果名字为空则取线路ID
						String name = (String) (oConvertUtils.isNotEmpty(tr.getProperty("name"))?tr.getProperty("name"):tr.getId());
						m.put("Transition", name);
						PvmActivity ac = tr.getDestination(); // 获取线路的终点节点
						m.put("nextnode",ac.getId());
						trans.add(m);
					}
				}
				break;
			}
		}
		return trans;
	}

	@Override
	public List<Map<String, Object>> getHistTaskNodeList(String proceInsId) {
		return activitiMapper.getHistTaskNodeList(proceInsId);
	}

	@Override
	public List<ActHiActinstDTO> getActHiActinstStartAndEnd(String proceInsId) {
		return activitiMapper.getActHiActinstStartAndEnd(proceInsId);
	}
	

	@Override
	public String getProcessStartUserId(String proceInsId) {
		return activitiMapper.getProcessStartUserId(proceInsId);
	}

	@Override
	public List<Map<String, Object>> getProcessEndUserId(String proceInsId) {
		return activitiMapper.getProcessEndUserId(proceInsId);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public synchronized void  goProcessTaskNode(String taskId, String nextTaskId, Map<String, Object> variables) throws Exception {  
	        List<Task> taskList = findTaskListByKey(findProcessInstanceByTaskId(taskId).getId(), findTaskById(taskId).getTaskDefinitionKey());
	        for (Task task : taskList) {
	        	if(taskId.equals(task.getId())){
	        		 commitProcess(task.getId(), variables, nextTaskId); 
	        	}
	        } 
    }
	
	 /** 
     * 根据流程实例ID和任务key值查询所有同级任务集合 
     *  
     * @param processInstanceId 
     * @param key 
     * @return 
     */  
    private  List<Task> findTaskListByKey(String processInstanceId, String key) {  
        return taskService.createTaskQuery().processInstanceId(  
                processInstanceId).taskDefinitionKey(key).list();  
    }  
    
    /** 
     * @param taskId 
     *            当前任务ID 
     * @param variables 
     *            流程变量 
     * @param activityId 
     *            流程转向执行任务节点ID<br> 
     *            此参数为空，默认为提交操作 
     * @throws Exception 
     */  
    private  void commitProcess(String taskId, Map<String, Object> variables,String activityId) throws Exception {  
       
        // 跳转节点为空，默认提交操作  
        if (oConvertUtils.isEmpty(activityId)) {  
            taskService.complete(taskId, variables);  
        } else {// 流程转向操作  
            turnTransition(taskId, activityId, variables);  
        }  
    }
    
    /** 
     * 根据任务ID获取对应的流程实例 
     *  
     * @param taskId 
     *            任务ID 
     * @return 
     * @throws Exception 
     */  
    public  ProcessInstance findProcessInstanceByTaskId(String taskId)  
            throws Exception {  
        // 找到流程实例  
        ProcessInstance processInstance = runtimeService  
                .createProcessInstanceQuery().processInstanceId(  
                        findTaskById(taskId).getProcessInstanceId())  
                .singleResult();  
        if (processInstance == null) {   
            throw new Exception("流程实例未找到!");  
        }  
        return processInstance;  
    }  
    
    
    /** 
     * 流程转向操作 
     *  
     * @param taskId 
     *            当前任务ID 
     * @param activityId 
     *            目标节点任务ID 
     * @param variables 
     *            流程变量 
     * @throws Exception 
     */  
    private  void turnTransition(String taskId, String activityId,  
            Map<String, Object> variables) throws Exception {  
        // 当前节点  
        ActivityImpl currActivity = findActivitiImpl(taskId, null);
        
        // 清空当前流向  
        List<PvmTransition> oriPvmTransitionList = clearTransition(currActivity);  
  
        // 创建新流向  
        TransitionImpl newTransition = currActivity.createOutgoingTransition();  
        // 目标节点  
        ActivityImpl pointActivity = findActivitiImpl(taskId, activityId);  
        try {
			// 设置新流向的目标节点  
			newTransition.setDestination(pointActivity);
			
			// 多分支模式，点击button动态给选择分支加监听
			//List<PvmTransition> pvmTransitionList = currActivity.getOutgoingTransitions();
			for(PvmTransition pv:oriPvmTransitionList){
				if(activityId.equals(pv.getDestination().getId())){
					TransitionImpl tra = (TransitionImpl) pv;
					if(tra.getExecutionListeners()!=null && tra.getExecutionListeners().size()>0){
						newTransition.setExecutionListeners(tra.getExecutionListeners());
					}
					break;
				}
			}
  
			// 执行转向任务  
			taskService.complete(taskId, variables);
		} catch (Exception e) {
			throw e;
		} finally{
			// 删除目标节点新流入  
			pointActivity.getIncomingTransitions().remove(newTransition);  
			
			// 还原以前流向  
			restoreTransition(currActivity, oriPvmTransitionList); 
		}
    }  

    
    /** 
     * 根据任务ID和节点ID获取活动节点 <br> 
     *  
     * @param taskId 
     *            任务ID 
     * @param activityId 
     *            活动节点ID <br> 
     *            如果为null或""，则默认查询当前活动节点 <br> 
     *            如果为"end"，则查询结束节点 <br> 
     *  
     * @return 
     * @throws Exception 
     */  
    private  ActivityImpl findActivitiImpl(String taskId, String activityId)  
            throws Exception {  
        // 取得流程定义  
        ProcessDefinitionEntity processDefinition = findProcessDefinitionEntityByTaskId(taskId);  
  
        // 获取当前活动节点ID  
        if (oConvertUtils.isEmpty(activityId)) {  
            activityId = findTaskById(taskId).getTaskDefinitionKey();  
        }  
  
        // 根据流程定义，获取该流程实例的结束节点  
        if (activityId.toUpperCase().equals("END")) {  
            for (ActivityImpl activityImpl : processDefinition.getActivities()) {  
                List<PvmTransition> pvmTransitionList = activityImpl  
                        .getOutgoingTransitions();  
                if (pvmTransitionList.isEmpty()) {  
                    return activityImpl;  
                }  
            }  
        }  
  
        // 根据节点ID，获取对应的活动节点  
        ActivityImpl activityImpl = ((ProcessDefinitionImpl) processDefinition)  
                .findActivity(activityId);  
  
        return activityImpl;  
    }
    
    /** 
     * 根据任务ID获取流程定义 
     *  
     * @param taskId 
     *            任务ID 
     * @return 
     * @throws Exception 
     */  
    public  ProcessDefinitionEntity findProcessDefinitionEntityByTaskId(  
            String taskId) throws Exception {  
        // 取得流程定义  
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)  
                .getDeployedProcessDefinition(findTaskById(taskId)  
                        .getProcessDefinitionId());  
  
        if (processDefinition == null) {  
            throw new Exception("流程定义未找到!");  
        }  
  
        return processDefinition;  
    }  
    
    /** 
     * 根据任务ID获得任务实例 
     *  
     * @param taskId 
     *            任务ID 
     * @return 
     * @throws Exception 
     */  
    private TaskEntity findTaskById(String taskId) throws Exception {  
        TaskEntity task = (TaskEntity) taskService.createTaskQuery().taskId(taskId).singleResult();  
        if (task == null) {  
            throw new Exception("任务实例未找到!");  
        }  
        return task;  
    }  
    
    /** 
     * 清空指定活动节点流向 
     *  
     * @param activityImpl 
     *            活动节点 
     * @return 节点流向集合 
     */  
    private  List<PvmTransition> clearTransition(ActivityImpl activityImpl) {  
        // 存储当前节点所有流向临时变量  
        List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();  
        // 获取当前节点所有流向，存储到临时变量，然后清空  
        List<PvmTransition> pvmTransitionList = activityImpl  
                .getOutgoingTransitions();  
        for (PvmTransition pvmTransition : pvmTransitionList) {  
            oriPvmTransitionList.add(pvmTransition);  
        }  
        pvmTransitionList.clear();  
  
        return oriPvmTransitionList;  
    }
    
    /** 
     * 	还原指定活动节点流向 
     *  
     * @param activityImpl 
     *  	活动节点 
     * @param oriPvmTransitionList 
     * 	原有节点流向集合 
     */  
    private  void restoreTransition(ActivityImpl activityImpl,  
            List<PvmTransition> oriPvmTransitionList) {  
        // 清空现有流向  
        List<PvmTransition> pvmTransitionList = activityImpl  
                .getOutgoingTransitions();  
        pvmTransitionList.clear();  
        // 还原以前流向  
        for (PvmTransition pvmTransition : oriPvmTransitionList) {  
            pvmTransitionList.add(pvmTransition);  
        }  
    }

	/**
     * 	指定下一步操作人
     * @param processInstanceId
     * @param taskDefKey
     */
    @Override
    public String getTaskIdByProins(String proInsId,String taskDefKey){
		List<String> list = activitiMapper.getTaskIdByProins(proInsId, taskDefKey);
		if(list!=null&&list.size()>0) {
			return list.get(0);
		}
		return null;
    }

	@Override
	public String getHisVarinst(String varName, String proInsId) {
		return activitiMapper.getHisVarinst(varName, proInsId);
	}

	@Override
	public List<UserAgentDTO> getUserAgent(Date currDate) {
		return activitiMapper.getUserAgent(currDate);
	}

	@Override
	public void updateBpmStatus(String procInstId, String bpmStatus) {
		LambdaQueryWrapper<ExtActFlowData> queryWrapper = new LambdaQueryWrapper<ExtActFlowData>();
		//queryWrapper.eq(ExtActFlowData::getFormDataId, businessKey);
		queryWrapper.eq(ExtActFlowData::getProcessInstId, procInstId);
		ExtActFlowData extActFlowData = extActFlowDataMapper.selectOne(queryWrapper);
		//更新表单状态
		if(extActFlowData!=null) {
			String tableName = extActFlowData.getFormTableName().toUpperCase();
			String col = extActFlowData.getBpmStatusField().toUpperCase();
			if(oConvertUtils.isEmpty(col)) {
				col = "BPM_STATUS";
			}
			extActProcessMapper.updateBpmStatusById(tableName, extActFlowData.getFormDataId(), col, bpmStatus);
			extActFlowData.setBpmStatus(bpmStatus);
			extActFlowDataMapper.updateById(extActFlowData);
		}
	}

	@Override
	@Transactional
	public void suspend(String procInstId) {
		runtimeService.suspendProcessInstanceById(procInstId);
		updateBpmStatus(procInstId, WorkFlowGlobals.BPM_BUS_STATUS_5);
	}

	@Override
	@Transactional
	public void restart(String procInstId) {
		runtimeService.activateProcessInstanceById(procInstId);
		updateBpmStatus(procInstId, WorkFlowGlobals.BPM_BUS_STATUS_2);
		
	} 

}
